home *** CD-ROM | disk | FTP | other *** search
- /* eigen/test.c
- *
- * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /* Author: G. Jungman
- */
-
- #include <config.h>
- #include <stdlib.h>
- #include <gsl/gsl_test.h>
- #include <gsl/gsl_math.h>
- #include <gsl/gsl_blas.h>
- #include <gsl/gsl_ieee_utils.h>
- #include <gsl/gsl_complex_math.h>
- #include <gsl/gsl_eigen.h>
-
- gsl_matrix *
- create_hilbert_matrix(int size)
- {
- int i, j;
- gsl_matrix * m = gsl_matrix_alloc(size, size);
- for(i=0; i<size; i++) {
- for(j=0; j<size; j++) {
- gsl_matrix_set(m, i, j, 1.0/(i+j+1.0));
- }
- }
- return m;
- }
-
- gsl_matrix *
- create_random_symm_matrix(int size)
- {
- int i, j;
- unsigned long k = 1;
- gsl_matrix * m = gsl_matrix_alloc(size, size);
- for(i=0; i<size; i++) {
- for(j=i; j<size; j++) {
- double x;
- k = (69069 * k + 1) & 0xffffffffUL;
- x = k / 4294967296.0;
- gsl_matrix_set(m, i, j, x);
- gsl_matrix_set(m, j, i, x);
- }
- }
- return m;
- }
-
- gsl_matrix_complex *
- create_random_herm_matrix(int size)
- {
- int i, j;
- unsigned long k = 1;
- gsl_matrix_complex * m = gsl_matrix_complex_alloc(size, size);
- for(i=0; i<size; i++) {
- for(j=i; j<size; j++) {
- gsl_complex z;
- k = (69069 * k + 1) & 0xffffffffUL;
- GSL_REAL(z) = k / 4294967296.0;
- k = (69069 * k + 1) & 0xffffffffUL;
- GSL_IMAG(z) = (i == j) ? 0 : k / 4294967296.0;
- gsl_matrix_complex_set(m, i, j, z);
- gsl_matrix_complex_set(m, j, i, gsl_complex_conjugate(z));
- }
- }
- return m;
- }
-
- void
- test_eigen_results (size_t N, const gsl_matrix * m, const gsl_vector * eval,
- const gsl_matrix * evec, const char * desc,
- const char * desc2)
- {
- size_t i,j;
-
- gsl_vector * x = gsl_vector_alloc(N);
- gsl_vector * y = gsl_vector_alloc(N);
-
- /* check eigenvalues */
-
- for (i = 0; i < N; i++)
- {
- double ei = gsl_vector_get (eval, i);
- gsl_vector_const_view vi = gsl_matrix_const_column(evec, i);
- gsl_vector_memcpy(x, &vi.vector);
- /* compute y = m x (should = lambda v) */
- gsl_blas_dgemv (CblasNoTrans, 1.0, m, x, 0.0, y);
- for (j = 0; j < N; j++)
- {
- double xj = gsl_vector_get (x, j);
- double yj = gsl_vector_get (y, j);
- gsl_test_rel(yj, ei * xj, 1e8 * GSL_DBL_EPSILON,
- "%s, eigenvalue(%d,%d), %s", desc, i, j, desc2);
- }
- }
-
- /* check eigenvectors are orthonormal */
-
- for (i = 0; i < N; i++)
- {
- gsl_vector_const_view vi = gsl_matrix_const_column(evec, i);
- double nrm_v = gsl_blas_dnrm2(&vi.vector);
- gsl_test_rel (nrm_v, 1.0, N * GSL_DBL_EPSILON, "%s, normalized(%d), %s",
- desc, i, desc2);
- }
-
- for (i = 0; i < N; i++)
- {
- gsl_vector_const_view vi = gsl_matrix_const_column(evec, i);
- for (j = i + 1; j < N; j++)
- {
- gsl_vector_const_view vj = gsl_matrix_const_column(evec, j);
- double vivj;
- gsl_blas_ddot (&vi.vector, &vj.vector, &vivj);
- gsl_test_abs (vivj, 0.0, N * GSL_DBL_EPSILON,
- "%s, orthogonal(%d,%d), %s", desc, i, j, desc2);
- }
- }
-
- gsl_vector_free(x);
- gsl_vector_free(y);
- }
-
-
- void
- test_eigenvalues (size_t N, const gsl_vector *eval, const gsl_vector * eval2,
- const char * desc, const char * desc2)
- {
- size_t i;
- for (i = 0; i < N; i++)
- {
- double ei = gsl_vector_get (eval, i);
- double e2i = gsl_vector_get (eval2, i);
- gsl_test_rel(ei, e2i, GSL_DBL_EPSILON, "%s, direct eigenvalue(%d), %s",
- desc, i, desc2);
- }
- }
-
-
- void
- test_eigen_complex_results (size_t N, const gsl_matrix_complex * m,
- const gsl_vector * eval,
- const gsl_matrix_complex * evec,
- const char * desc,
- const char * desc2)
- {
- size_t i,j;
-
- gsl_vector_complex * x = gsl_vector_complex_alloc(N);
- gsl_vector_complex * y = gsl_vector_complex_alloc(N);
-
- /* check eigenvalues */
-
- for (i = 0; i < N; i++)
- {
- double ei = gsl_vector_get (eval, i);
- gsl_vector_complex_const_view vi = gsl_matrix_complex_const_column(evec, i);
- gsl_vector_complex_memcpy(x, &vi.vector);
- /* compute y = m x (should = lambda v) */
- gsl_blas_zgemv (CblasNoTrans, GSL_COMPLEX_ONE, m, x,
- GSL_COMPLEX_ZERO, y);
- for (j = 0; j < N; j++)
- {
- gsl_complex xj = gsl_vector_complex_get (x, j);
- gsl_complex yj = gsl_vector_complex_get (y, j);
- gsl_test_rel(GSL_REAL(yj), ei * GSL_REAL(xj), 1e8*GSL_DBL_EPSILON,
- "%s, eigenvalue(%d,%d), real, %s", desc, i, j, desc2);
- gsl_test_rel(GSL_IMAG(yj), ei * GSL_IMAG(xj), 1e8*GSL_DBL_EPSILON,
- "%s, eigenvalue(%d,%d), imag, %s", desc, i, j, desc2);
- }
- }
-
- /* check eigenvectors are orthonormal */
-
- for (i = 0; i < N; i++)
- {
- gsl_vector_complex_const_view vi = gsl_matrix_complex_const_column(evec, i);
- double nrm_v = gsl_blas_dznrm2(&vi.vector);
- gsl_test_rel (nrm_v, 1.0, N * GSL_DBL_EPSILON, "%s, normalized(%d), %s",
- desc, i, desc2);
- }
-
- for (i = 0; i < N; i++)
- {
- gsl_vector_complex_const_view vi = gsl_matrix_complex_const_column(evec, i);
- for (j = i + 1; j < N; j++)
- {
- gsl_vector_complex_const_view vj
- = gsl_matrix_complex_const_column(evec, j);
- gsl_complex vivj;
- gsl_blas_zdotc (&vi.vector, &vj.vector, &vivj);
- gsl_test_abs (gsl_complex_abs(vivj), 0.0, N * GSL_DBL_EPSILON,
- "%s, orthogonal(%d,%d), %s", desc, i, j, desc2);
- }
- }
-
- gsl_vector_complex_free(x);
- gsl_vector_complex_free(y);
- }
-
-
- void
- test_eigen_symm(const char * desc, const gsl_matrix * m)
- {
- size_t N = m->size1;
-
- gsl_matrix * A = gsl_matrix_alloc(N, N);
- gsl_matrix * evec = gsl_matrix_alloc(N, N);
- gsl_vector * eval = gsl_vector_alloc(N);
- gsl_vector * eval2 = gsl_vector_alloc(N);
-
- gsl_eigen_symm_workspace * w1 = gsl_eigen_symm_alloc (N);
- gsl_eigen_symmv_workspace * w2 = gsl_eigen_symmv_alloc (N);
-
- gsl_matrix_memcpy(A, m);
- gsl_eigen_symmv(A, eval, evec, w2);
- test_eigen_results (N, m, eval, evec, desc, "unsorted");
-
- gsl_matrix_memcpy(A, m);
- gsl_eigen_symm(A, eval2, w1);
- test_eigenvalues (N, eval, eval2, desc, "unsorted");
-
- gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_VAL_ASC);
- test_eigen_results (N, m, eval, evec, desc, "val/asc");
-
- gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_VAL_DESC);
- test_eigen_results (N, m, eval, evec, desc, "val/desc");
-
- gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_ABS_ASC);
- test_eigen_results (N, m, eval, evec, desc, "abs/asc");
-
- gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_VAL_DESC);
- test_eigen_results (N, m, eval, evec, desc, "abs/desc");
-
- gsl_eigen_symm_free (w1);
- gsl_eigen_symmv_free (w2);
-
- gsl_matrix_free(A);
- gsl_matrix_free(evec);
- gsl_vector_free(eval);
- gsl_vector_free(eval2);
- }
-
-
- void
- test_eigen_herm(const char * desc, const gsl_matrix_complex * m)
- {
- size_t N = m->size1;
-
- gsl_matrix_complex * A = gsl_matrix_complex_alloc(N, N);
- gsl_matrix_complex * evec = gsl_matrix_complex_alloc(N, N);
- gsl_vector * eval = gsl_vector_alloc(N);
- gsl_vector * eval2 = gsl_vector_alloc(N);
-
- gsl_eigen_herm_workspace * w1 = gsl_eigen_herm_alloc (N);
- gsl_eigen_hermv_workspace * w2 = gsl_eigen_hermv_alloc (N);
-
- gsl_matrix_complex_memcpy(A, m);
- gsl_eigen_hermv(A, eval, evec, w2);
- test_eigen_complex_results (N, m, eval, evec, desc, "unsorted");
-
- gsl_matrix_complex_memcpy(A, m);
- gsl_eigen_herm(A, eval2, w1);
- test_eigenvalues (N, eval, eval2, desc, "unsorted");
-
- gsl_eigen_hermv_sort (eval, evec, GSL_EIGEN_SORT_VAL_ASC);
- test_eigen_complex_results (N, m, eval, evec, desc, "val/asc");
-
- gsl_eigen_hermv_sort (eval, evec, GSL_EIGEN_SORT_VAL_DESC);
- test_eigen_complex_results (N, m, eval, evec, desc, "val/desc");
-
- gsl_eigen_hermv_sort (eval, evec, GSL_EIGEN_SORT_ABS_ASC);
- test_eigen_complex_results (N, m, eval, evec, desc, "abs/asc");
-
- gsl_eigen_hermv_sort (eval, evec, GSL_EIGEN_SORT_VAL_DESC);
- test_eigen_complex_results (N, m, eval, evec, desc, "abs/desc");
-
- gsl_eigen_herm_free (w1);
- gsl_eigen_hermv_free (w2);
-
- gsl_matrix_complex_free(A);
- gsl_matrix_complex_free(evec);
- gsl_vector_free(eval);
- gsl_vector_free(eval2);
- }
-
-
- void
- test_eigen_jacobi(const char * desc, const gsl_matrix * m)
- {
- size_t N = m->size1;
- unsigned int nrot;
-
- gsl_matrix * A = gsl_matrix_alloc(N, N);
- gsl_matrix * evec = gsl_matrix_alloc(N, N);
- gsl_vector * eval = gsl_vector_alloc(N);
-
- gsl_matrix_memcpy(A, m);
- gsl_eigen_jacobi(A, eval, evec, 1000, &nrot);
- gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
-
- test_eigen_results (N, m, eval, evec, desc, "");
-
- gsl_matrix_free(A);
- gsl_matrix_free(evec);
- gsl_vector_free(eval);
- }
-
-
- int test_invert_jacobi(void)
- {
- int s = 0;
- int i, j;
- gsl_matrix * hminv = gsl_matrix_alloc(10, 10);
- gsl_matrix * id = gsl_matrix_alloc(10, 10);
-
- /* 10x10 Hilbert matrix */
- gsl_matrix * hm = create_hilbert_matrix(10);
- gsl_eigen_invert_jacobi(hm, hminv, 1000);
-
- /* gsl_linalg_matmult(hm, hminv, id); */
- gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, hm, hminv, 0.0, id);
-
- for(i=0; i<10; i++) {
- for(j=0; j<10; j++) {
- double delta_ij = ( i == j ? 1.0 : 0.0 );
- double id_ij = gsl_matrix_get(id, i, j);
- int rs = ( fabs(id_ij - delta_ij) > 5.0e-3 );
- s += rs;
- }
- }
-
- gsl_matrix_free(hm);
- gsl_matrix_free(hminv);
- gsl_matrix_free(id);
-
- return s;
- }
-
- int main()
- {
- gsl_matrix *rs10 = create_random_symm_matrix (10);
- gsl_matrix_complex *rh10 = create_random_herm_matrix (10);
-
- double r[] = { 0, 0, -1, 0,
- 0, 1, 0, 1,
- -1, 0, 0, 0,
- 0, 1, 0, 0 };
-
- double c[] = { 0,0, 0,0, -1,0, 0,0,
- 0,0, 1,0, 0,0, 1,0,
- -1,0, 0,0, 0,0, 0,0,
- 0,0, 1,0, 0,0, 0,0 };
-
- gsl_matrix_view s4 = gsl_matrix_view_array (r, 4, 4);
- gsl_matrix_complex_view h4 = gsl_matrix_complex_view_array (c, 4, 4);
-
- gsl_ieee_env_setup ();
-
- test_eigen_symm("symm(4)", &s4.matrix);
- test_eigen_herm("herm(4)", &h4.matrix);
-
- test_eigen_symm("symm(10)", rs10);
- test_eigen_herm("herm(10)", rh10);
-
- /* gsl_matrix *h5 = create_hilbert_matrix (5); */
- /* test_eigen_jacobi("hilbert(5)", h5); */
- /* test_invert_jacobi(); */
- /* gsl_matrix_free (h5); */
-
- gsl_matrix_complex_free (rh10);
- gsl_matrix_free (rs10);
-
- exit (gsl_test_summary());
- }
-